package com.pap.activitiy.controller.activity;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletResponse;

import org.activiti.engine.IdentityService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.pap.logback.builder.LogbackLoggerBuilder;


@RestController
@RequestMapping("/v1/activity/demo")
public class ActivityDemoController {

	private static Logger logger = LogbackLoggerBuilder.getLogger(ActivityDemoController.class.getName());

	@Autowired
	private TaskService taskService;

	@Autowired
	private ProcessEngine processEngine;
	
	@Autowired
	private RepositoryService repositoryService;
	
	@Autowired
	private IdentityService identityService;

	@RequestMapping("/index")
	public String index() {
		System.out.println("################################taskService" + taskService);
		System.out.println("################################processEngine" + processEngine);
		return "xxxxxxxxxxxxx";
	}

	/**
	 * 初始化一个任务
	 *  @param startUserId 流程发起人	发起流程时需要确定流程发起人	14693732217267200
	 */
	@RequestMapping("/startProcessInstanceById/{startUserId}")
	public void startProcessInstanceById(@PathVariable("startUserId") String startUserId, HttpServletResponse response) throws Exception {
		RuntimeService runtimeService = processEngine.getRuntimeService();

		Map<String, Object> variables = new HashMap<>();
		variables.put("userid", "10010");
		variables.put("day", 3);
		
		// businessKey	我们在做工作流的时候一定是需要将我们的业务和工作流来关联起来的，
		// 而Activiti给我们提供了一个便利就是Business_key,而这个字段就是专门用来存储我们的业务关键字。
		// // 获取业务键 产生规则(类名.主键)： className+“.”+ objId
		String businessKey = "ActivitiLeaveBillDTO." + new Random().nextInt(10000);
		
		// 当流程启动之后可以到表ACT_HI_PROCINST中查看字段START_USER_ID_的值来验证是否生效。
		identityService.setAuthenticatedUserId(startUserId);
		ProcessInstance processInstance = runtimeService.startProcessInstanceById("process:3:15008", businessKey, variables);
		
		// TODO 流程添加标题
		// runtimeService.setProcessInstanceName(processInstance.getId(), "流程名称");
	}
	
	/**
	 * 初始化一个任务
	 *  @param startUserId 流程发起人	发起流程时需要确定流程发起人	14693732217267200
	 */
	@RequestMapping("/startProcessInstanceByKey/{startUserId}")
	public void startProcessInstanceByKey(@PathVariable("startUserId") String startUserId, HttpServletResponse response) throws Exception {
		RuntimeService runtimeService = processEngine.getRuntimeService();

		Map<String, Object> variables = new HashMap<>();
		variables.put("userid", "10010");
		variables.put("day", 3);

		// businessKey	我们在做工作流的时候一定是需要将我们的业务和工作流来关联起来的，
		// 而Activiti给我们提供了一个便利就是Business_key,而这个字段就是专门用来存储我们的业务关键字。
		// // 获取业务键 产生规则(类名.主键)： className+“.”+ objId
		String businessKey = "ActivitiLeaveBillDTO." + new Random().nextInt(10000);
				
		// 当流程启动之后可以到表ACT_HI_PROCINST中查看字段START_USER_ID_的值来验证是否生效。
		identityService.setAuthenticatedUserId(startUserId);

		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("processId", businessKey, variables);

		// TODO 流程添加标题
		// runtimeService.setProcessInstanceName(processInstance.getId(), "流程名称");
	}
	
	/**
	 * 初始化一个任务- 含业务编号
	 * 	如果某一个busKey业务编号对应的流程实例被删除之后，仍然可以使用这个流程实例再次发起一个流程
	 * 	这样可以做到某一个流程被强制删除，业务方修改业务数据之后，再次提交当前业务编号对应的流程
	 *  @param startUserId 流程发起人	发起流程时需要确定流程发起人	14693732217267200
	 */
	@RequestMapping("/startProcessInstanceByKey/{startUserId}/{busKey}")
	public void startProcessInstanceByKey(@PathVariable("startUserId") String startUserId, 
			@PathVariable("busKey") String busKey, 
			HttpServletResponse response) throws Exception {
		RuntimeService runtimeService = processEngine.getRuntimeService();

		Map<String, Object> variables = new HashMap<>();
		variables.put("userid", "10010");
		variables.put("day", 3);

		// businessKey	我们在做工作流的时候一定是需要将我们的业务和工作流来关联起来的，
		// 而Activiti给我们提供了一个便利就是Business_key,而这个字段就是专门用来存储我们的业务关键字。
		// // 获取业务键 产生规则(类名.主键)： className+“.”+ objId
		String businessKey = "ActivitiLeaveBillDTO." + busKey;
				
		// 当流程启动之后可以到表ACT_HI_PROCINST中查看字段START_USER_ID_的值来验证是否生效。
		identityService.setAuthenticatedUserId(startUserId);

		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("processId", businessKey, variables);

		// TODO 流程添加标题
		// runtimeService.setProcessInstanceName(processInstance.getId(), "流程名称");
	}
	
	/**
	 * Key和Name的值为：bpmn文件process节点的id和name的属性值
	 * key属性被用来区别不同的流程定义。
	 * 带有特定key的流程定义第一次部署时，version为1。之后每次部署都会在当前最高版本号上加1
	 * Id的值的生成规则为:{processDefinitionKey}:{processDefinitionVersion}:{generated-id}, 这里的generated-id是一个自动生成的唯一的数字
	 * 重复部署一次，deploymentId的值以一定的形式变化
	 * 流程定义(ProcessDefinition)在数据库中没有相应的表对应，只是从act_ge_bytearray表中取出相应的bpmn和png图片，并进行解析。
	 * @throws Exception
	 */
	@RequestMapping("/selectprocess")
	public void selectProcess() throws Exception {

		List<ProcessDefinition> processDefinition = repositoryService.createProcessDefinitionQuery()
				.orderByProcessDefinitionVersion().desc().list();
		for (ProcessDefinition pd : processDefinition) {
			System.out.println("----------------------------------------------");
			System.out.println("流程定义名：" + pd.getResourceName());
			System.out.println("流程定义版本：" + pd.getVersion());
			System.out.println("流程定义KEY：" + pd.getKey());
			System.out.println("流程部署Deploymentid：" + pd.getDeploymentId());
			System.out.println("流程定义id：" + pd.getId());
		}

		List<ProcessDefinition> processDefinitionLast = repositoryService.createProcessDefinitionQuery()
				.orderByProcessDefinitionVersion().desc()// 查询所有的数据
				.latestVersion().list();// 查询所有流程的最新版本
		for (ProcessDefinition pd : processDefinitionLast) {
			System.out.println("----------------------------------------------");
			System.out.println("最新流程定义名：" + pd.getResourceName());
			System.out.println("最新流程定义版本：" + pd.getVersion());
			System.out.println("最新流程定义KEY：" + pd.getKey());
			System.out.println("最新流程部署Deploymentid：" + pd.getDeploymentId());
			System.out.println("最新流程定义id：" + pd.getId());
		}
	}
}
